arm64: add kernel config option to set securelevel when in Secure Boot mode
authorLinn Crosetto <linn@hpe.com>
Tue, 30 Aug 2016 17:54:38 +0000 (11:54 -0600)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 12 Jan 2017 15:52:37 +0000 (15:52 +0000)
Add a kernel configuration option to enable securelevel, to restrict
userspace's ability to modify the running kernel when UEFI Secure Boot is
enabled. Based on the x86 patch by Matthew Garrett.

Determine the state of Secure Boot in the EFI stub and pass this to the
kernel using the FDT.

Signed-off-by: Linn Crosetto <linn@hpe.com>
Gbp-Pq: Topic features/all/securelevel
Gbp-Pq: Name arm64-add-kernel-config-option-to-set-securelevel-wh.patch

arch/arm64/Kconfig
drivers/firmware/efi/arm-init.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/fdt.c
include/linux/efi.h

index 969ef880d234e3b340713948eb2e9aec8ba0b3a3..9b27a55d6e41325941a14f7353407b59a785babc 100644 (file)
@@ -977,6 +977,19 @@ config EFI
          allow the kernel to be booted as an EFI application. This
          is only useful on systems that have UEFI firmware.
 
+config EFI_SECURE_BOOT_SECURELEVEL
+       def_bool n
+       depends on SECURITY_SECURELEVEL
+       depends on EFI
+       prompt "Automatically set securelevel when UEFI Secure Boot is enabled"
+       ---help---
+         UEFI Secure Boot provides a mechanism for ensuring that the
+         firmware will only load signed bootloaders and kernels. Certain
+         use cases may also require that the kernel restrict any userspace
+         mechanism that could insert untrusted code into the kernel.
+         Say Y here to automatically enable securelevel enforcement
+         when a system boots with UEFI Secure Boot enabled.
+
 config DMI
        bool "Enable support for SMBIOS (DMI) tables"
        depends on EFI
index 8efe13075c922e6b79131af4af2d897245b94a42..6089026e9d239d1d08d64cc648afe358590d1653 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/of_fdt.h>
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
+#include <linux/security.h>
 
 #include <asm/efi.h>
 
@@ -244,6 +245,12 @@ void __init efi_init(void)
             "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
              efi.memmap.desc_version);
 
+#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL
+       if (params.secure_boot > 0) {
+               set_securelevel(1);
+       }
+#endif
+
        if (uefi_init() < 0)
                return;
 
index 1ac199cd75e7bdd56ce8d5b9ab91bc2ee9d15133..b6dc2953a8842a0c3603e3f174a48b0a89b7bf12 100644 (file)
@@ -582,7 +582,8 @@ static __initdata struct params fdt_params[] = {
        UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
        UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
        UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
-       UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
+       UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver),
+       UEFI_PARAM("Secure Boot Enabled", "linux,uefi-secure-boot", secure_boot)
 };
 
 static __initdata struct params xen_fdt_params[] = {
index d1cb612ecbc9edb0fea4bc624a9c9ca754b02490..61ad972f0f8b0e57b9e74395f8ac2286e48130ce 100644 (file)
@@ -20,7 +20,7 @@
 
 bool __nokaslr;
 
-static int efi_get_secureboot(efi_system_table_t *sys_table_arg)
+int efi_get_secureboot(efi_system_table_t *sys_table_arg)
 {
        static efi_char16_t const sb_var_name[] = {
                'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
index ee49cd23ee636d96b7d340ee74577ff8aef50822..97a329a7c25284fdec2fb58b5e41b83b3e2b097f 100644 (file)
@@ -62,4 +62,5 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
 
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
 
+int efi_get_secureboot(efi_system_table_t *sys_table_arg);
 #endif
index a6a93116a8f053f6c14911376ffa6da7f1dff44e..dc786dcdb3dd369d0b1549dcf57550ff8568ad5b 100644 (file)
@@ -139,6 +139,13 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
                        return efi_status;
                }
        }
+
+       fdt_val32 = cpu_to_fdt32(efi_get_secureboot(sys_table));
+       status = fdt_setprop(fdt, node, "linux,uefi-secure-boot",
+                            &fdt_val32, sizeof(fdt_val32));
+       if (status)
+               goto fdt_set_fail;
+
        return EFI_SUCCESS;
 
 fdt_set_fail:
index 937d619f8ee93abaa288ca2f3dc5191c807144ad..6ac44d01c7733eefd5f1a2ffac50d447abd1eec0 100644 (file)
@@ -716,6 +716,7 @@ struct efi_fdt_params {
        u32 mmap_size;
        u32 desc_size;
        u32 desc_ver;
+       u32 secure_boot;
 };
 
 typedef struct {